package com.pt.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

@Slf4j
public class FileUtil {
    
    /**
     * 保存文件到指定路径
     */
    public static String saveFile(MultipartFile file, String basePath, String filename) {
        try {
            // 创建目录
            Path directory = Paths.get(basePath);
            if (!Files.exists(directory)) {
                Files.createDirectories(directory);
            }
            
            // 保存文件
            Path filePath = directory.resolve(filename);
            Files.write(filePath, file.getBytes());
            
            log.info("文件保存成功: {}", filePath.toString());
            return filePath.toString();
        } catch (IOException e) {
            log.error("文件保存失败", e);
            return null;
        }
    }
    
    /**
     * 读取文件内容
     */
    public static byte[] readFile(String filePath) {
        try {
            Path path = Paths.get(filePath);
            return Files.readAllBytes(path);
        } catch (IOException e) {
            log.error("文件读取失败: {}", filePath, e);
            return null;
        }
    }
    
    /**
     * 验证是否为有效的种子文件
     */
    public static boolean isValidTorrentFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            log.error("文件为空");
            return false;
        }
        
        String filename = file.getOriginalFilename();
        if (filename == null || !filename.toLowerCase().endsWith(".torrent")) {
            log.error("文件扩展名不是.torrent");
            return false;
        }
        
        try {
            byte[] data = file.getBytes();
            if (data.length == 0) {
                log.error("文件大小为0");
                return false;
            }

            // 验证Bencode格式
            Map<String, Object> torrentData = BencodeUtil.decodeTorrent(data);
            if (torrentData == null) {
                log.error("无法解析Bencode格式");
                return false;
            }

            // 验证必需字段
            if (!torrentData.containsKey("info")) {
                log.error("缺少info字段");
                return false;
            }

            Map<String, Object> info = (Map<String, Object>) torrentData.get("info");
            if (info == null) {
                log.error("info字段无效");
                return false;
            }

            // 验证info字段的必需属性
            if (!info.containsKey("piece length")) {
                log.error("缺少piece length字段");
                return false;
            }

            if (!info.containsKey("pieces")) {
                log.error("缺少pieces字段");
                return false;
            }

            // 验证pieces字段长度是否为20的倍数
            byte[] pieces = ((String) info.get("pieces")).getBytes(StandardCharsets.ISO_8859_1);
            if (pieces.length % 20 != 0) {
                log.error("pieces字段长度不是20的倍数");
                return false;
            }

            // 验证文件信息
            if (!info.containsKey("name")) {
                log.error("缺少name字段");
                return false;
            }

            if (info.containsKey("files")) {
                // 多文件模式
                List<Map<String, Object>> files = (List<Map<String, Object>>) info.get("files");
                if (files.isEmpty()) {
                    log.error("files列表为空");
                    return false;
                }
                for (Map<String, Object> fileInfo : files) {
                    if (!fileInfo.containsKey("length") || !fileInfo.containsKey("path")) {
                        log.error("文件信息缺少必需字段");
                        return false;
                    }
                }
            } else if (!info.containsKey("length")) {
                // 单文件模式必须有length字段
                log.error("缺少length字段");
                return false;
            }

            return true;
        } catch (Exception e) {
            log.error("验证种子文件时发生错误", e);
            return false;
        }
    }
    
    /**
     * 保存种子文件，并确保其完整性
     */
    public static void saveTorrentFile(MultipartFile file, String directory, String filename) throws IOException {
        // 确保目录存在
        File dir = new File(directory);
        if (!dir.exists() && !dir.mkdirs()) {
            throw new IOException("无法创建目录: " + directory);
        }

        // 读取文件数据
        byte[] data = file.getBytes();
        
        // 验证并规范化种子文件
        Map<String, Object> torrentData = BencodeUtil.decodeTorrent(data);
        if (torrentData == null) {
            throw new IOException("无法解析种子文件");
        }

        // 确保info字典中有private标志
        Map<String, Object> info = (Map<String, Object>) torrentData.get("info");
        if (info != null && !info.containsKey("private")) {
            info.put("private", 1L);
        }

        // 重新编码种子文件
        byte[] normalizedData = BencodeUtil.encodeTorrent(torrentData);
        if (normalizedData == null) {
            throw new IOException("无法重新编码种子文件");
        }

        // 保存文件
        File destFile = new File(dir, filename);
        java.nio.file.Files.write(destFile.toPath(), normalizedData);
    }
    
    /**
     * 删除文件
     */
    public static boolean deleteFile(String filePath) {
        try {
            Path path = Paths.get(filePath);
            return Files.deleteIfExists(path);
        } catch (IOException e) {
            log.error("文件删除失败: {}", filePath, e);
            return false;
        }
    }
    
    /**
     * 格式化文件大小
     */
    public static String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.2f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", size / (1024.0 * 1024.0));
        } else if (size < 1024L * 1024 * 1024 * 1024) {
            return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
        } else {
            return String.format("%.2f TB", size / (1024.0 * 1024.0 * 1024.0 * 1024.0));
        }
    }
} 